package cn.xinfei.xdecision.common.service.datax.datamanage.v2.impl;

import cn.xinfei.xdecision.common.dao.datax.datamanage.v2.VariableSnapshotMapper;
import cn.xinfei.xdecision.common.model.datax.datamanage.request.DeriveVarSnapshotDetailVO;
import cn.xinfei.xdecision.common.model.datax.datamanage.request.DeriveVarSnapshotVO;
import cn.xinfei.xdecision.common.model.datax.datamanage.v2.VariableSnapshot;
import cn.xinfei.xdecision.common.model.datax.datamanage.v2.vo.VariableResumeVO;
import cn.xinfei.xdecision.common.service.common.DataConvertUtil;
import cn.xinfei.xdecision.common.service.datax.datamanage.v2.VariableSnapshotService;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;


@Service
public class VariableSnapshotServiceImpl extends ServiceImpl<VariableSnapshotMapper, VariableSnapshot> implements VariableSnapshotService {

    @Resource
    VariableSnapshotMapper variableSnapshotMapper;


    @Override
    public List<VariableSnapshot> findByVarCode(String varCode) {
        return new LambdaQueryChainWrapper<>(variableSnapshotMapper)
                .eq(StringUtils.isNotBlank(varCode), VariableSnapshot::getVarCode, varCode)
                .list();
    }

    @Override
    public DeriveVarSnapshotVO getSnapshotInfo(String varCode, Long versionId, Long organId) {
        VariableSnapshot varSnapshot = variableSnapshotMapper.findByVarCodeAndVersion(varCode, organId, versionId);
        return Optional.ofNullable(varSnapshot)
                .map(VariableSnapshot::getSnapshot)
                .map(snap -> JSON.parseObject(snap, DeriveVarSnapshotVO.class))
                .orElseGet(DeriveVarSnapshotVO::new);
    }

    @Override
    public List<DeriveVarSnapshotDetailVO> getSnapshotDetails(String varCode, Long organId) {
        List<VariableSnapshot> varSnapshotList = variableSnapshotMapper.findByVarCode(varCode, organId);
        return Optional.ofNullable(varSnapshotList)
                .orElseGet(Collections::emptyList)
                .stream()
                .map(snap -> {
                    DeriveVarSnapshotVO deriveVarSnapshotVO = JSON.parseObject(snap.getSnapshot(), DeriveVarSnapshotVO.class);
                    deriveVarSnapshotVO.setVersionId(snap.getVersion());
                    deriveVarSnapshotVO.setUpdateTime(snap.getUpdateTime());
                    return deriveVarSnapshotVO;
                })
                .map(DataConvertUtil::fromDeriveVarSnapshotVO)
                .collect(Collectors.toList());
    }

    @Override
    public void logicalDelete(String varCode, Long organId) {
        variableSnapshotMapper.logicalDelete(varCode, organId);
    }

    @Override
    public List<VariableSnapshot> findByVarCodes(Collection<String> varCodes, Long organId) {
        return Optional.ofNullable(variableSnapshotMapper.findByVarCodes(varCodes, organId))
                .orElse(Collections.emptyList());
    }

    @Override
    public boolean checkVarCodeUsedInSnapshot(Collection<String> varCodes,Long organId) {
        AtomicBoolean checkInSnapshot = new AtomicBoolean(false);
        if (CollectionUtils.isEmpty(varCodes)) {
            return checkInSnapshot.get();
        }
        Optional.ofNullable(variableSnapshotMapper.findAllVarCodes(organId))
                .orElse(Collections.emptyList())
                .parallelStream()
                .filter(snap -> Objects.nonNull(snap) && StringUtils.isNotBlank(snap.getSnapshot()))
                .map(snap -> JSON.parseObject(snap.getSnapshot(), VariableResumeVO.class))
                .filter(Objects::nonNull)
                .map(VariableResumeVO::getParameterVariables)
                .flatMap(Collection::stream)
                .map(paramVarCode -> StringUtils.split(paramVarCode, ","))
                .map(Arrays::asList)
                .flatMap(Collection::stream)
                .distinct()
                .filter(varCodes::contains)
                .findFirst()
                .ifPresent(varCode -> {
                    if(StringUtils.isNotBlank(varCode)) {
                        checkInSnapshot.set(true);
                    }
                });
        return checkInSnapshot.get();
    }


}
